package com.quantum.collection
{

	import flash.utils.Dictionary;

	public class DictionarySet implements Set
	{

		private var _length:int=0;

		private var _set:Dictionary;

		public function DictionarySet(useWeakReferences:Boolean=false)
		{
			_set=new Dictionary(useWeakReferences);
		}

		public function get length():int
		{
			return _length;
		}

		public function add(item:*):void
		{
			if (!_set[item])
			{
				_length++;
			}
			else
			{
				return;
			}
			_set[item]=true;
		}

		public function addCollection(items:Array):void
		{
			if (!items)
			{
				return;
			}
			for each (var item:Object in items)
			{
				add(item);
			}
		}

		public function addSet(set:DictionarySet):void
		{
			set.forEach(function(item:*):void
				{
					add(item);
				});
		}

		public function remove(item:*):void
		{
			if (_set[item])
			{
				_length--;
			}
			else
			{
				return;
			}
			delete _set[item];
		}

		public function contains(item:*):Boolean
		{
			return _set[item];
		}

		/**
		 * Executes a test function on each item in the set and removes items that
		 * return <code>false</code> for the test function.
		 *
		 * @param job
		 *    The function to execute, in form of:
		 *    <code>function job(item:*):Boolean;</code>
		 */
		public function filter(job:Function):void
		{
			for (var item:*in _set)
			{
				if (!job(item))
				{
					remove(item);
				}
			}
		}

		/**
		 * Invokes the given 'job' function for each item in this set one by one, treating the
		 * item as the argument to the method. If the optional arg is provided, it serves as
		 * the second argument to the invoked method. The return value contains the values
		 * returned by the job, keyed on the items in the set.
		 */
		public function forEach(job:Function, arg:*=null):Dictionary
		{
			var returnValueByItem:Dictionary=new Dictionary();
			var returnVal:Object;
			if (arg)
			{
				for (var item:*in _set)
				{
					returnVal=job(item, arg);
					returnValueByItem[item]=returnVal;
				}
			}
			else
			{
				for (item in _set)
				{
					returnVal=job(item);
					returnValueByItem[item]=returnVal;
				}
			}
			return returnValueByItem;
		}

		/**
		 * Returns an item that does not satisfy the given test function if any such item is
		 * found in the set. Otherwise returns null.
		 */
		public function every(test:Function, arg:*=null, breakOn:Boolean=false):*
		{
			if (arg)
			{
				for (var item:*in _set)
				{
					if (test(item, arg) == breakOn)
					{
						return item;
					}
				}
			}
			else
			{
				for (item in _set)
				{
					if (test(item) == breakOn)
					{
						return item;
					}
				}
			}
		}

		/**
		 * Returns an array containing all of the elements in this set
		 */
//		public function toArray():Array
//		{
//			return MixedUtil.getKeys(_set);
//		}



		protected function get set():Dictionary
		{
			return _set;
		}

		protected function setLength(len:int):void
		{
			_length=len;
		}
	} // class

}